<h1>Creating Custom Drush Commands</h1>
<p>
Creating a new drush command is very easy.  Follow these simple steps:
<ol>
<li>Create a command file called COMMANDFILE.drush.inc

<li>Implement the function COMMANDFILE_drush_command()

<li>Implement the functions that your commands will call.
    These will usually be named drush_COMMANDFILE_COMMANDNAME().
</ol><p>
For an example drush command, see examples/sandwich.drush.inc.
The steps for implementing your command are explained in more
detail below.

<h2>Create COMMANDFILE.drush.inc</h2>
<p>
The name of your drush command is very important.  It must end
in ".drush.inc" to be recognized as a drush command.  The part
of the filename that comes before the ".drush.inc" becomes the
name of the commandfile.  Optionally, the commandfile may be restricted
to a particular version of Drupal by adding a ".dVERSION" after
the name of the commandfile (e.g. ".d8.drush.inc")  Your commandfile name
is used by drush to compose the names of the functions it will call, so
choose wisely.
<p>
The example drush command, 'make-me-a-sandwich', is stored
in the 'sandwich' commandfile, 'sandwich.drush.inc'.  You can
find this file in the 'examples' directory in the drush distribution.
<p>
Drush searches for commandfiles in the following locations:
<ul>
<li>The "/path/to/drush/commands" folder.

<li>Folders listed in the 'include' option (see `drush topic docs-configuration`).

<li>The system-wide drush commands folder, e.g. /usr/share/drush/commands

<li>The ".drush" folder in the user's HOME folder.

<li>/drush and /sites/all/drush in the current Drupal installation

<li>All enabled modules in the current Drupal installation

<li>Folders and files containing other versions of drush in their names will
be *skipped* (e.g. devel.drush4.inc or drush4/devel.drush.inc).  Names
containing the current version of drush (e.g. devel.drush5.inc) will be loaded.</li>
</ul> <p>
Note that modules in the current Drupal installation will only
be considered if drush has bootstrapped to at least the DRUSH_BOOSTRAP_SITE
level.  Usually, when working with a Drupal site, drush will
bootstrap to DRUSH_BOOTSTRAP_FULL; in this case, only the drush
commandfiles in enabled modules will be considered eligible for
loading.  If drush only bootstraps to DRUSH_BOOTSTRAP_SITE,
though, then all drush commandfiles will be considered, whether the
module is enabled or not.  See `drush topic docs-bootstrap` for
more information on bootstrapping.
<p>
Additionally, drush commandfiles may optionally define a function
COMMANDFILE_drush_load() in the file COMMANDFILE.drush.load.inc.
If this function returns FALSE, then the commandfile will not be loaded.

<h2>Implement COMMANDFILE_drush_command()</h2>
<p>
The drush_command hook is the most important part of the
commandfile.  It returns an array of items that define
how your commands should be called, and how they work.
Drush commands are very similar to the Drupal menu system.
The elements that can appear in a drush command definition
are shown below.
<ul>
<li>'aliases':

     Provides a list of shorter names for the command.
     For example, pm-download may also be called via `drush dl`.
     If the alias is used, drush will substitute back in the
     primary command name, so pm-download will still be used
     to generate the command hook, etc.

<li>'command-hook':

     Change the name of the function drush will
     call to execute the command from drush_COMMANDFILE_COMMANDNAME()
     to drush_COMMANDFILE_COMMANDHOOK(), where COMMANDNAME is the
     original name of the command, and COMMANDHOOK is the value
     of the 'command-hook' item.

<li>'callback':

     Name of function to invoke for this command.  The callback
     function name _must_ begin with "drush_commandfile_", where commandfile
     is from the file "commandfile.drush.inc", which contains the
     commandfile_drush_command() function that returned this command.
     Note that the callback entry is optional; it is preferable to
     omit it, in which case drush_invoke() will generate the hook function name.

<li>'callback arguments':

     An array of arguments to pass to the callback.
     The command line arguments, if any, will appear after the
     callback arguments in the function parameters.

<li>'description':

     Description of the command.

<li>'arguments':

     An array of arguments that are understood by the command.
     Used by `drush help` only.

<li>'required-arguments':

     Defaults to FALSE; TRUE if all of the arguments are required.
     Set to an integer count of required arguments if only some are
     required.

<li>'options':

     An array of options that are understood by the command.
     Any option that the command expects to be able to query via
     drush_get_option _must_ be listed in the options array.
     If it is not, users will get an error about an "Unknown option"
     when they try to specify the option on the command line.
<p>
     The value of each option may be either a simple string containing
     the option description, or an array containing the following
     information:

     <ul>
          <li>'description': A description of the option.
          <li>'example-value': An example value to show in help.
          <li>'value': optional|required.
          <li>'required': This option must be passed.
          <li>'hidden': The option is not shown in the help output (rare).
     </ul>

<li>'allow-additional-options':

     If TRUE, then the ordinary testing to see if options exist
     will be skipped.  Examples of where this is done includes
     the core-rsync command, which passes options along to the
     rsync shell command.
     <p>
     This item may also contain a list of other commands that
     are invoked as subcommands (e.g. the pm-update
     command calls pm-updatecode and updatedb commands).  When
     this is done, the options from the subcommand may be used
     on the commandline, and are also listed in the command's
     `help` output.
     <p>
     Defaults to FALSE.

<li>'examples':

     An array of examples that are understood by the command.
     Used by `drush help` only.

<li>'scope':

     One of 'system', 'project', 'site'.  Not currently used.

<li>'bootstrap':

     Drupal bootstrap level.  Valid values are:
<ul>
      <li>DRUSH_BOOTSTRAP_DRUSH
      <li>DRUSH_BOOTSTRAP_DRUPAL_ROOT
      <li>DRUSH_BOOTSTRAP_DRUPAL_SITE
      <li>DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION
      <li>DRUSH_BOOTSTRAP_DRUPAL_DATABASE
      <li>DRUSH_BOOTSTRAP_DRUPAL_FULL
      <li>DRUSH_BOOTSTRAP_DRUPAL_LOGIN
      <li>DRUSH_BOOTSTRAP_MAX
</ul>
     The default value is DRUSH_BOOTSTRAP_DRUPAL_LOGIN.

     See `drush topic docs-bootstrap`.

<li>'core':

     Drupal major version required. Append a '+' to indicate 'and later versions.'

<li>'drupal dependencies':

     Drupal modules required for this command.

<li>'drush dependencies':

     Other drush commandfiles required for this command.

<li>'engines':

    Provides a list of Drush engines to load with this command.  The set
    of appropriate engines varies by command.
<ul>
   <li>'outputformat':

       One important engine is the 'outputformat' engine.  This engine is
       responsible for formatting the structured data (usually an associative
       array) that a Drush command returns as its function result into a
       human-readable or machine-parsable string.

       Some of the options that may be used with output format engines
       are listed below; however, each specific output format type can take
       additional option items that control the way that the output is rendered.
       See the comment in the output format's implementation for information. The
       Drush core output format engines can be found in commands/core/outputformat.
  <ul>
     <li>'default':

          The default type to render output as. If declared, the command should
          not print any output on its own, but instead should return a data
          structure (usually an associative array) that can be rendered by the
          output type selected.

     <li>'pipe-format':

          When the command is executed in --pipe mode, the command output will
          be rendered by the format specified by the pipe-format item instead of
          the default format.  Note that in either event, the user may specify
          the format to use via the --format command-line option.

     <li>'formatted-filter' and 'pipe-filter':

          Specifies a function callback that will be used to filter the command
          result.  The filter is selected based on the type of output format
          object selected.  Most output formatters are 'pipe' formatters, that
          produce machine-parsable output.  A few formatters, such as 'table'
          and 'key-value' are 'formatted' filter types, that produce
          human-readable output.
  </ul>
</ul>
<li>'topics':

     Provides a list of topic commands that are related in
     some way to this command.  Used by `drush help`.

<li>'topic':

     Set to TRUE if this command is a topic, callable from the
     `drush docs-topics` command.

<li>'category':

     Set this to override the category in which your command is listed in help.
</ul><p>
The 'sandwich' drush_command hook looks like this:
<pre>
        function sandwich_drush_command() {
          $items = array();

          $items['make-me-a-sandwich'] = array(
            'description' => "Makes a delicious sandwich.",
            'arguments' => array(
              'filling' => 'The type of the sandwich (turkey, cheese, etc.)',
            ),
            'options' => array(
              'spreads' => 'Comma delimited list of spreads (e.g. mayonnaise, mustard)',
            ),
            'examples' => array(
              'drush mmas turkey --spreads=ketchup,mustard' => 'Make a terrible-tasting sandwich that is lacking in pickles.',
            ),
            'aliases' => array('mmas'),
            'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap at all.
          );

          return $items;
        }
</pre><p>
Most of the items in the 'make-me-a-sandwich' command
definition have no effect on execution, and are used only
by `drush help`.  The exceptions are 'aliases' (described
above) and 'bootstrap'.  As previously mentioned,
`drush topic docs-bootstrap` explains the drush bootstrapping
process in detail.

<h2>Implement drush_COMMANDFILE_COMMANDNAME()</h2>
<p>
The 'make-me-a-sandwich' command in sandwich.drush.inc
is defined as follows:
<pre>
	function drush_sandwich_make_me_a_sandwich($filling = 'ascii') {
	  ... implementation here ...
        }
</pre><p>
If a user runs `drush make-me-a-sandwich` with no command line
arguments, then drush will call drush_sandwich_make_me_a_sandwich()
with no function parameters; in this case, $filling will take on
the provided default value, 'ascii'.  (If there is no default
value provided, then the variable will be NULL, and a warning
will be printed.)  Running `drush make-me-a-sandwich ham` will
cause drush to call drush_sandwich_make_me_a_sandwich('ham').  In
the same way, commands that take two command line arguments can
simply define two functional parameters, and a command that takes
a variable number of command line arguments can use the standard
php function func_get_args() to get them all in an array for easy
processing.
<p>
It is also very easy to query the command options using the
function drush_get_option().  For example, in the drush_sandwich_make_me_a_sandwich()
function, the --spreads option is retrieved as follows:
<pre>
        $str_spreads = '';
        if ($spreads = drush_get_option('spreads')) {
          $list = implode(' and ', explode(',', $spreads));
          $str_spreads = ' with just a dash of ' . $list;
        }
</pre><p>
Note that drush will actually call a sequence of functions before
and after your drush command function.  One of these hooks is the
"validate" hook.  The 'sandwich' commandfile provides a validate
hook for the 'make-me-a-sandwich' command:
<pre>
        function drush_sandwich_make_me_a_sandwich_validate() {
          $name = posix_getpwuid(posix_geteuid());
          if ($name['name'] !== 'root') {
            return drush_set_error('MAKE_IT_YOUSELF', dt('What? Make your own sandwich.'));
          }
        }
</pre><p>
The validate function should call drush_set_error and return
its result if the command cannot be validated for some reason.
See `drush topic docs-policy` for more information on defining
policy functions with validate hooks, and `drush topic docs-api`
for information on how the command hook process works.  Also,
the list of defined drush error codes can be found in
`drush topic docs-errorcodes`.
<p>
To see the full implementation of the sample 'make-me-a-sandwich'
command, see `drush topic docs-examplecommand`.
